# -*- coding: utf-8 -*-
# @Time    : 2024/7/11 13:35
# @Author  : yujiahao
# @File    : 14_fastapi_header.py
# @description:Header 参数


'''
定义 Header 参数的方式与定义 Query、Path、Cookie 参数相同。
Header 是 Path、Query、Cookie 的兄弟类，都继承自共用的 Param 类。

注意，从 fastapi 导入的 Query、Path、Header 等对象，实际上是返回特殊类的函数。
必须使用 Header 声明 header 参数，否则该参数会被解释为查询参数。
'''

from typing import Annotated

# 声明 Header 参数
from fastapi import FastAPI, Header

app = FastAPI()


@app.get("/items/")
# 使用和 Path、Query、Cookie 一样的结构定义 header 参数，第一个值是默认值，还可以传递所有验证参数或注释参数
async def read_items(user_agent: Annotated[str | None, Header()] = None):
    '''
    user_agent 是一个常见的 HTTP 请求头字段，用于标识客户端的应用程序、操作系统、供应商以及版本信息。
    这个字段通常由浏览器或其他客户端自动生成并包含在每个 HTTP 请求中。

    作用
        识别客户端类型：服务器可以通过 User-Agent 字段来识别请求来自哪种类型的客户端（如浏览器、移动设备、爬虫等）。
        内容定制：服务器可以根据 User-Agent 的信息返回特定于客户端的内容。例如，返回适合移动设备的页面。
        统计与分析：网站分析工具可以使用 User-Agent 字段来统计访问者的浏览器和操作系统的分布情况。
    结构
        User-Agent 字段的值通常包含多个部分，每个部分提供不同的信息。一个典型的 User-Agent 字段值可能如下：

        Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36

    这个字符串可以分解为以下部分：

        Mozilla/5.0：历史原因，几乎所有浏览器都包含这一部分。
        (Windows NT 10.0; Win64; x64)：操作系统和平台信息。
        AppleWebKit/537.36：浏览器引擎信息（WebKit）。
        (KHTML, like Gecko)：兼容性信息，表示与 Gecko 引擎兼容。
        Chrome/91.0.4472.124：浏览器名称和版本号。
        Safari/537.36：另一个兼容性标识，表示与 Safari 浏览器兼容。

    '''
    return {"User-Agent": user_agent}


# 自动转换
@app.get("/items_2/")
async def read_items(
        strange_header: Annotated[str | None, Header(convert_underscores=False)] = None,
):
    '''
        - Header 比 Path、Query 和 Cookie 提供了更多功能。

        - 大部分标准请求头用连字符分隔，即减号（-）。

        - 但是 user-agent 这样的变量在 Python 中是无效的。

        - 因此，默认情况下，Header 把参数名中的字符由下划线（_）改为连字符（-）来提取并存档请求头 。

        - 同时，HTTP 的请求头不区分大小写，可以使用 Python 标准样式（即 snake_case）进行声明。

        - 因此，可以像在 Python 代码中一样使用 user_agent ，无需把首字母大写为 User_Agent 等形式。

        - 如需禁用下划线自动转换为连字符，可以把 Header 的 convert_underscores 参数设置为 False：

        - 注意，使用 convert_underscores = False 要慎重，有些 HTTP 代理和服务器不支持使用带有下划线的请求头。
    '''

    return {"strange_header": strange_header}


# 重复的请求头


@app.get("/items_3/")
async def read_items(x_token: Annotated[list[str] | None, Header()] = None):
    '''
    有时，可能需要接收重复的请求头。即同一个请求头有多个值。

    类型声明中可以使用 list 定义多个请求头。

    使用 Python list 可以接收重复请求头所有的值。

    例如，声明 X-Token 多次出现的请求头，可以写成这样
    '''
    return {"X-Token values": x_token}
